"""
输入验证和防护服务

提供参数验证、SQL注入防护、XSS防护和安全漏洞检测，包括：
- 参数验证机制
- SQL注入防护
- XSS攻击防护
- CSRF防护
- 文件上传安全检查
- 输入长度和格式验证
- 恶意代码检测
- 安全漏洞扫描
"""
import re
import html
import json
import hashlib
import secrets
import mimetypes
import urllib.parse
from typing import Dict, List, Any, Optional, Union, Tuple, Set
from datetime import datetime, timedelta
from dataclasses import dataclass, field
from enum import Enum
import logging

# 配置日志
logging.basicConfig(level=logging.INFO)
validation_logger = logging.getLogger('input_validation')


class ValidationLevel(Enum):
    """验证级别枚举"""
    BASIC = "basic"         # 基础验证
    STANDARD = "standard"   # 标准验证
    STRICT = "strict"       # 严格验证
    PARANOID = "paranoid"   # 极严格验证


class ThreatType(Enum):
    """威胁类型枚举"""
    SQL_INJECTION = "sql_injection"
    XSS = "xss"
    CSRF = "csrf"
    PATH_TRAVERSAL = "path_traversal"
    COMMAND_INJECTION = "command_injection"
    LDAP_INJECTION = "ldap_injection"
    XML_INJECTION = "xml_injection"
    SCRIPT_INJECTION = "script_injection"
    FILE_UPLOAD = "file_upload"
    BUFFER_OVERFLOW = "buffer_overflow"


class ValidationResult(Enum):
    """验证结果枚举"""
    VALID = "valid"
    INVALID = "invalid"
    SUSPICIOUS = "suspicious"
    DANGEROUS = "dangerous"


@dataclass
class ValidationRule:
    """验证规则"""
    rule_id: str
    name: str
    pattern: str
    threat_type: ThreatType
    severity: str = "medium"  # low, medium, high, critical
    description: str = ""
    is_active: bool = True


@dataclass
class ValidationReport:
    """验证报告"""
    input_data: str
    result: ValidationResult
    threats_detected: List[ThreatType] = field(default_factory=list)
    violations: List[str] = field(default_factory=list)
    sanitized_data: Optional[str] = None
    confidence_score: float = 0.0
    timestamp: datetime = field(default_factory=datetime.now)
    processing_time_ms: float = 0.0


@dataclass
class FileValidationResult:
    """文件验证结果"""
    filename: str
    is_valid: bool
    file_type: str
    file_size: int
    threats: List[str] = field(default_factory=list)
    sanitized_filename: Optional[str] = None
    allowed_extensions: List[str] = field(default_factory=list)


@dataclass
class SecurityEvent:
    """安全事件"""
    event_id: str
    event_type: str
    threat_type: Optional[ThreatType]
    input_data: str
    source_ip: Optional[str] = None
    user_agent: Optional[str] = None
    timestamp: datetime = field(default_factory=datetime.now)
    severity: str = "medium"
    blocked: bool = False
    details: Dict[str, Any] = field(default_factory=dict)


class InputValidationService:
    """输入验证和防护服务"""
    
    def __init__(self, validation_level: ValidationLevel = ValidationLevel.STANDARD):
        self.validation_level = validation_level
        
        # 存储
        self.validation_rules: Dict[str, ValidationRule] = {}
        self.security_events: List[SecurityEvent] = []
        self.blocked_ips: Set[str] = set()
        self.rate_limits: Dict[str, List[datetime]] = {}
        
        # 配置
        self.config = {
            'max_input_length': 10000,
            'max_file_size': 10 * 1024 * 1024,  # 10MB
            'allowed_file_extensions': ['.txt', '.pdf', '.doc', '.docx', '.xls', '.xlsx', '.csv', '.json'],
            'blocked_file_extensions': ['.exe', '.bat', '.cmd', '.sh', '.ps1', '.vbs', '.js', '.php', '.asp'],
            'max_requests_per_minute': 100,
            'auto_block_threshold': 5,
            'enable_csrf_protection': True,
            'enable_xss_protection': True,
            'enable_sql_injection_protection': True,
            'sanitize_html': True,
            'log_all_attempts': True
        }
        
        # 初始化验证规则
        self._initialize_validation_rules()
        
        # CSRF令牌存储
        self.csrf_tokens: Dict[str, datetime] = {}
    
    def _initialize_validation_rules(self):
        """初始化验证规则"""
        rules = [
            # SQL注入检测规则
            {
                'rule_id': 'sql_union',
                'name': 'SQL UNION注入检测',
                'pattern': r'(?i)\bunion\s+select\b',
                'threat_type': ThreatType.SQL_INJECTION,
                'severity': 'high',
                'description': '检测UNION SELECT注入攻击'
            },
            {
                'rule_id': 'sql_or_injection',
                'name': 'SQL OR注入检测',
                'pattern': r'(?i)\bor\s+[\'"]?\d+[\'"]?\s*=\s*[\'"]?\d+[\'"]?',
                'threat_type': ThreatType.SQL_INJECTION,
                'severity': 'high',
                'description': '检测OR条件注入攻击'
            },
            {
                'rule_id': 'sql_comment',
                'name': 'SQL注释注入检测',
                'pattern': r'(?i)(--|#|/\*|\*/)',
                'threat_type': ThreatType.SQL_INJECTION,
                'severity': 'medium',
                'description': '检测SQL注释符号'
            },
            {
                'rule_id': 'sql_drop_table',
                'name': 'SQL DROP TABLE检测',
                'pattern': r'(?i)\bdrop\s+table\b',
                'threat_type': ThreatType.SQL_INJECTION,
                'severity': 'critical',
                'description': '检测DROP TABLE攻击'
            },
            {
                'rule_id': 'sql_delete_from',
                'name': 'SQL DELETE FROM检测',
                'pattern': r'(?i)\bdelete\s+from\b',
                'threat_type': ThreatType.SQL_INJECTION,
                'severity': 'critical',
                'description': '检测DELETE FROM攻击'
            },
            
            # XSS攻击检测规则
            {
                'rule_id': 'xss_script_tag',
                'name': 'XSS Script标签检测',
                'pattern': r'(?i)<script[^>]*>.*?</script>',
                'threat_type': ThreatType.XSS,
                'severity': 'high',
                'description': '检测script标签XSS攻击'
            },
            {
                'rule_id': 'xss_javascript',
                'name': 'XSS JavaScript检测',
                'pattern': r'(?i)javascript\s*:',
                'threat_type': ThreatType.XSS,
                'severity': 'high',
                'description': '检测javascript:协议XSS攻击'
            },
            {
                'rule_id': 'xss_onerror',
                'name': 'XSS onerror事件检测',
                'pattern': r'(?i)onerror\s*=',
                'threat_type': ThreatType.XSS,
                'severity': 'high',
                'description': '检测onerror事件XSS攻击'
            },
            {
                'rule_id': 'xss_onload',
                'name': 'XSS onload事件检测',
                'pattern': r'(?i)onload\s*=',
                'threat_type': ThreatType.XSS,
                'severity': 'high',
                'description': '检测onload事件XSS攻击'
            },
            {
                'rule_id': 'xss_eval',
                'name': 'XSS eval函数检测',
                'pattern': r'(?i)\beval\s*\(',
                'threat_type': ThreatType.XSS,
                'severity': 'high',
                'description': '检测eval函数XSS攻击'
            },
            
            # 路径遍历攻击检测
            {
                'rule_id': 'path_traversal_dotdot',
                'name': '路径遍历..检测',
                'pattern': r'\.\.[\\/]',
                'threat_type': ThreatType.PATH_TRAVERSAL,
                'severity': 'high',
                'description': '检测../路径遍历攻击'
            },
            {
                'rule_id': 'path_traversal_encoded',
                'name': '编码路径遍历检测',
                'pattern': r'%2e%2e[%2f%5c]',
                'threat_type': ThreatType.PATH_TRAVERSAL,
                'severity': 'high',
                'description': '检测URL编码的路径遍历攻击'
            },
            
            # 命令注入检测
            {
                'rule_id': 'cmd_injection_pipe',
                'name': '命令注入管道检测',
                'pattern': r'[;&|`]',
                'threat_type': ThreatType.COMMAND_INJECTION,
                'severity': 'high',
                'description': '检测命令分隔符注入'
            },
            {
                'rule_id': 'cmd_injection_backtick',
                'name': '命令注入反引号检测',
                'pattern': r'`[^`]*`',
                'threat_type': ThreatType.COMMAND_INJECTION,
                'severity': 'high',
                'description': '检测反引号命令执行'
            },
            
            # LDAP注入检测
            {
                'rule_id': 'ldap_injection',
                'name': 'LDAP注入检测',
                'pattern': r'(?i)\(\s*[&|!]\s*\(',
                'threat_type': ThreatType.LDAP_INJECTION,
                'severity': 'medium',
                'description': '检测LDAP特殊字符注入'
            },
            
            # XML注入检测
            {
                'rule_id': 'xml_entity',
                'name': 'XML实体注入检测',
                'pattern': r'<!ENTITY',
                'threat_type': ThreatType.XML_INJECTION,
                'severity': 'medium',
                'description': '检测XML外部实体注入'
            }
        ]
        
        for rule_data in rules:
            rule = ValidationRule(**rule_data)
            self.validation_rules[rule.rule_id] = rule
    
    def validate_input(self, input_data: str, context: str = "general",
                      source_ip: Optional[str] = None,
                      user_agent: Optional[str] = None) -> ValidationReport:
        """验证输入数据"""
        start_time = datetime.now()
        
        try:
            # 基础检查
            if not isinstance(input_data, str):
                input_data = str(input_data)
            
            # 长度检查
            if len(input_data) > self.config['max_input_length']:
                return ValidationReport(
                    input_data=input_data[:100] + "...",
                    result=ValidationResult.INVALID,
                    violations=[f"输入长度超过限制: {len(input_data)} > {self.config['max_input_length']}"],
                    processing_time_ms=(datetime.now() - start_time).total_seconds() * 1000
                )
            
            # 威胁检测
            threats_detected = []
            violations = []
            confidence_score = 0.0
            
            for rule in self.validation_rules.values():
                if not rule.is_active:
                    continue
                
                if re.search(rule.pattern, input_data):
                    threats_detected.append(rule.threat_type)
                    violations.append(f"{rule.name}: {rule.description}")
                    
                    # 根据严重程度调整置信度
                    severity_scores = {'low': 0.1, 'medium': 0.3, 'high': 0.6, 'critical': 1.0}
                    confidence_score = max(confidence_score, severity_scores.get(rule.severity, 0.3))
            
            # 确定验证结果
            if not threats_detected:
                result = ValidationResult.VALID
            elif confidence_score >= 0.8:
                result = ValidationResult.DANGEROUS
            elif confidence_score >= 0.4:
                result = ValidationResult.SUSPICIOUS
            else:
                result = ValidationResult.INVALID
            
            # 数据清理
            sanitized_data = self._sanitize_input(input_data, threats_detected)
            
            # 记录安全事件
            if threats_detected:
                self._log_security_event(
                    event_type="threat_detected",
                    threat_type=threats_detected[0] if threats_detected else None,
                    input_data=input_data,
                    source_ip=source_ip,
                    user_agent=user_agent,
                    severity=self._get_max_severity(threats_detected),
                    blocked=result == ValidationResult.DANGEROUS,
                    details={
                        'context': context,
                        'threats': [t.value for t in threats_detected],
                        'violations': violations,
                        'confidence_score': confidence_score
                    }
                )
            
            processing_time = (datetime.now() - start_time).total_seconds() * 1000
            
            return ValidationReport(
                input_data=input_data,
                result=result,
                threats_detected=threats_detected,
                violations=violations,
                sanitized_data=sanitized_data,
                confidence_score=confidence_score,
                processing_time_ms=processing_time
            )
            
        except Exception as e:
            validation_logger.error(f"输入验证失败: {str(e)}")
            return ValidationReport(
                input_data=input_data,
                result=ValidationResult.INVALID,
                violations=[f"验证过程出错: {str(e)}"],
                processing_time_ms=(datetime.now() - start_time).total_seconds() * 1000
            )
    
    def validate_file_upload(self, filename: str, file_content: bytes,
                           allowed_types: Optional[List[str]] = None) -> FileValidationResult:
        """验证文件上传"""
        try:
            # 基础信息
            file_size = len(file_content)
            file_type = mimetypes.guess_type(filename)[0] or "unknown"
            
            # 文件名清理
            sanitized_filename = self._sanitize_filename(filename)
            
            # 大小检查
            threats = []
            if file_size > self.config['max_file_size']:
                threats.append(f"文件大小超过限制: {file_size} > {self.config['max_file_size']}")
            
            # 扩展名检查
            file_ext = '.' + filename.split('.')[-1].lower() if '.' in filename else ''
            
            if file_ext in self.config['blocked_file_extensions']:
                threats.append(f"危险文件扩展名: {file_ext}")
            
            allowed_extensions = allowed_types or self.config['allowed_file_extensions']
            if allowed_extensions and file_ext not in allowed_extensions:
                threats.append(f"不允许的文件扩展名: {file_ext}")
            
            # 文件内容检查
            content_threats = self._scan_file_content(file_content, file_ext)
            threats.extend(content_threats)
            
            # 文件名安全检查
            filename_threats = self._validate_filename(filename)
            threats.extend(filename_threats)
            
            is_valid = len(threats) == 0
            
            return FileValidationResult(
                filename=filename,
                is_valid=is_valid,
                file_type=file_type,
                file_size=file_size,
                threats=threats,
                sanitized_filename=sanitized_filename,
                allowed_extensions=allowed_extensions
            )
            
        except Exception as e:
            return FileValidationResult(
                filename=filename,
                is_valid=False,
                file_type="unknown",
                file_size=0,
                threats=[f"文件验证失败: {str(e)}"]
            )
    
    def generate_csrf_token(self, session_id: str) -> str:
        """生成CSRF令牌"""
        token = secrets.token_urlsafe(32)
        self.csrf_tokens[token] = datetime.now()
        
        # 清理过期令牌
        self._cleanup_expired_tokens()
        
        return token
    
    def validate_csrf_token(self, token: str, session_id: str) -> bool:
        """验证CSRF令牌"""
        if not self.config['enable_csrf_protection']:
            return True
        
        if token not in self.csrf_tokens:
            return False
        
        # 检查令牌是否过期（1小时）
        token_time = self.csrf_tokens[token]
        if datetime.now() - token_time > timedelta(hours=1):
            del self.csrf_tokens[token]
            return False
        
        return True
    
    def check_rate_limit(self, identifier: str, max_requests: Optional[int] = None) -> bool:
        """检查速率限制"""
        max_requests = max_requests or self.config['max_requests_per_minute']
        current_time = datetime.now()
        
        # 初始化或清理旧记录
        if identifier not in self.rate_limits:
            self.rate_limits[identifier] = []
        
        # 移除1分钟前的记录
        self.rate_limits[identifier] = [
            req_time for req_time in self.rate_limits[identifier]
            if current_time - req_time < timedelta(minutes=1)
        ]
        
        # 检查是否超过限制
        if len(self.rate_limits[identifier]) >= max_requests:
            return False
        
        # 记录当前请求
        self.rate_limits[identifier].append(current_time)
        return True
    
    def add_validation_rule(self, name: str, pattern: str, threat_type: ThreatType,
                          severity: str = "medium", description: str = "") -> str:
        """添加自定义验证规则"""
        try:
            # 验证正则表达式
            re.compile(pattern)
            
            rule_id = f"custom_{int(datetime.now().timestamp() * 1000)}_{secrets.token_hex(4)}"
            
            rule = ValidationRule(
                rule_id=rule_id,
                name=name,
                pattern=pattern,
                threat_type=threat_type,
                severity=severity,
                description=description
            )
            
            self.validation_rules[rule_id] = rule
            
            validation_logger.info(f"添加验证规则: {rule_id} - {name}")
            
            return rule_id
            
        except re.error as e:
            raise ValueError(f"无效的正则表达式: {str(e)}")
    
    def remove_validation_rule(self, rule_id: str) -> bool:
        """移除验证规则"""
        if rule_id in self.validation_rules:
            del self.validation_rules[rule_id]
            validation_logger.info(f"移除验证规则: {rule_id}")
            return True
        return False
    
    def block_ip(self, ip_address: str, reason: str = "") -> None:
        """封禁IP地址"""
        self.blocked_ips.add(ip_address)
        
        self._log_security_event(
            event_type="ip_blocked",
            threat_type=None,
            input_data="",
            source_ip=ip_address,
            severity="high",
            blocked=True,
            details={'reason': reason}
        )
        
        validation_logger.warning(f"封禁IP地址: {ip_address} - {reason}")
    
    def unblock_ip(self, ip_address: str) -> bool:
        """解封IP地址"""
        if ip_address in self.blocked_ips:
            self.blocked_ips.remove(ip_address)
            validation_logger.info(f"解封IP地址: {ip_address}")
            return True
        return False
    
    def is_ip_blocked(self, ip_address: str) -> bool:
        """检查IP是否被封禁"""
        return ip_address in self.blocked_ips
    
    def _sanitize_input(self, input_data: str, threats: List[ThreatType]) -> str:
        """清理输入数据"""
        sanitized = input_data
        
        # HTML转义和XSS清理
        if self.config['sanitize_html'] or ThreatType.XSS in threats:
            sanitized = html.escape(sanitized)
            # 移除危险的JavaScript函数
            dangerous_js_patterns = [
                r'(?i)\beval\s*\(',
                r'(?i)javascript\s*:',
                r'(?i)vbscript\s*:'
            ]
            for pattern in dangerous_js_patterns:
                sanitized = re.sub(pattern, '', sanitized)
        
        # SQL注入清理
        if ThreatType.SQL_INJECTION in threats:
            # 移除危险的SQL关键字和字符
            dangerous_patterns = [
                r'(?i)\bunion\s+select\b',
                r'(?i)\bdrop\s+table\b',
                r'(?i)\bdelete\s+from\b',
                r'(?i)\binsert\s+into\b',
                r'(?i)\bupdate\s+set\b',
                r'--',
                r'/\*',
                r'\*/',
                r'#'
            ]
            
            for pattern in dangerous_patterns:
                sanitized = re.sub(pattern, '', sanitized)
        
        # 路径遍历清理
        if ThreatType.PATH_TRAVERSAL in threats:
            sanitized = sanitized.replace('..', '').replace('\\', '').replace('/', '')
        
        # 命令注入清理
        if ThreatType.COMMAND_INJECTION in threats:
            dangerous_chars = ['&', '|', ';', '`', '$', '(', ')', '<', '>']
            for char in dangerous_chars:
                sanitized = sanitized.replace(char, '')
        
        return sanitized
    
    def _sanitize_filename(self, filename: str) -> str:
        """清理文件名"""
        # 移除路径遍历
        sanitized = filename.replace('..', '').replace('/', '').replace('\\', '')
        
        # 移除危险字符
        dangerous_chars = ['<', '>', ':', '"', '|', '?', '*', '\0']
        for char in dangerous_chars:
            sanitized = sanitized.replace(char, '_')
        
        # 移除控制字符
        sanitized = ''.join(char for char in sanitized if ord(char) >= 32)
        
        # 确保文件名不为空
        if not sanitized or sanitized.isspace():
            sanitized = "unnamed_file"
        
        # 限制长度
        if len(sanitized) > 255:
            name, ext = sanitized.rsplit('.', 1) if '.' in sanitized else (sanitized, '')
            max_name_len = 255 - len(ext) - 1 if ext else 255
            sanitized = name[:max_name_len] + ('.' + ext if ext else '')
        
        return sanitized
    
    def _validate_filename(self, filename: str) -> List[str]:
        """验证文件名"""
        threats = []
        
        # 检查路径遍历
        if '..' in filename or '/' in filename or '\\' in filename:
            threats.append("文件名包含路径遍历字符")
        
        # 检查空字节
        if '\0' in filename:
            threats.append("文件名包含空字节")
        
        # 检查保留名称（Windows）
        reserved_names = ['CON', 'PRN', 'AUX', 'NUL', 'COM1', 'COM2', 'COM3', 'COM4', 
                         'COM5', 'COM6', 'COM7', 'COM8', 'COM9', 'LPT1', 'LPT2', 
                         'LPT3', 'LPT4', 'LPT5', 'LPT6', 'LPT7', 'LPT8', 'LPT9']
        
        base_name = filename.split('.')[0].upper()
        if base_name in reserved_names:
            threats.append(f"文件名使用了保留名称: {base_name}")
        
        # 检查长度
        if len(filename) > 255:
            threats.append(f"文件名过长: {len(filename)} > 255")
        
        return threats
    
    def _scan_file_content(self, content: bytes, file_ext: str) -> List[str]:
        """扫描文件内容"""
        threats = []
        
        try:
            # 尝试解码为文本进行检查
            text_content = content.decode('utf-8', errors='ignore')
            
            # 检查脚本内容
            script_patterns = [
                r'<script[^>]*>',
                r'javascript:',
                r'vbscript:',
                r'onload\s*=',
                r'onerror\s*=',
                r'eval\s*\(',
                r'document\.write',
                r'window\.location'
            ]
            
            for pattern in script_patterns:
                if re.search(pattern, text_content, re.IGNORECASE):
                    threats.append(f"文件内容包含可疑脚本: {pattern}")
            
            # 检查可执行文件头
            if content.startswith(b'MZ') or content.startswith(b'\x7fELF'):
                threats.append("文件可能是可执行文件")
            
            # 检查PHP标签
            if b'<?php' in content or b'<?' in content:
                threats.append("文件包含PHP代码")
            
            # 检查ASP标签
            if b'<%' in content and b'%>' in content:
                threats.append("文件包含ASP代码")
            
        except Exception as e:
            validation_logger.warning(f"文件内容扫描失败: {str(e)}")
        
        return threats
    
    def _get_max_severity(self, threats: List[ThreatType]) -> str:
        """获取威胁的最高严重程度"""
        if not threats:
            return "low"
        
        severity_levels = {"low": 1, "medium": 2, "high": 3, "critical": 4}
        max_severity = "low"
        
        for threat in threats:
            for rule in self.validation_rules.values():
                if rule.threat_type == threat:
                    if severity_levels.get(rule.severity, 1) > severity_levels.get(max_severity, 1):
                        max_severity = rule.severity
        
        return max_severity
    
    def _log_security_event(self, event_type: str, threat_type: Optional[ThreatType],
                          input_data: str, source_ip: Optional[str] = None,
                          user_agent: Optional[str] = None, severity: str = "medium",
                          blocked: bool = False, details: Optional[Dict[str, Any]] = None):
        """记录安全事件"""
        event = SecurityEvent(
            event_id=f"event_{int(datetime.now().timestamp() * 1000)}_{secrets.token_hex(4)}",
            event_type=event_type,
            threat_type=threat_type,
            input_data=input_data[:200] + "..." if len(input_data) > 200 else input_data,
            source_ip=source_ip,
            user_agent=user_agent,
            severity=severity,
            blocked=blocked,
            details=details or {}
        )
        
        self.security_events.append(event)
        
        # 记录到日志
        if self.config['log_all_attempts']:
            validation_logger.info(
                f"Security Event: {event_type} - Threat: {threat_type.value if threat_type else 'None'} - "
                f"IP: {source_ip} - Severity: {severity} - Blocked: {blocked}"
            )
        
        # 自动封禁检查
        if source_ip and severity in ['high', 'critical']:
            self._check_auto_block(source_ip)
        
        # 限制事件历史大小
        if len(self.security_events) > 10000:
            self.security_events = self.security_events[-5000:]
    
    def _check_auto_block(self, ip_address: str):
        """检查是否需要自动封禁IP"""
        if ip_address in self.blocked_ips:
            return
        
        # 统计最近1小时内的高危事件
        recent_time = datetime.now() - timedelta(hours=1)
        high_risk_events = [
            event for event in self.security_events
            if (event.source_ip == ip_address and 
                event.timestamp > recent_time and 
                event.severity in ['high', 'critical'])
        ]
        
        if len(high_risk_events) >= self.config['auto_block_threshold']:
            self.block_ip(ip_address, f"自动封禁: {len(high_risk_events)}次高危事件")
    
    def _cleanup_expired_tokens(self):
        """清理过期的CSRF令牌"""
        current_time = datetime.now()
        expired_tokens = [
            token for token, timestamp in self.csrf_tokens.items()
            if current_time - timestamp > timedelta(hours=1)
        ]
        
        for token in expired_tokens:
            del self.csrf_tokens[token]
    
    def get_security_events(self, source_ip: Optional[str] = None,
                          threat_type: Optional[ThreatType] = None,
                          severity: Optional[str] = None,
                          limit: int = 100) -> List[Dict[str, Any]]:
        """获取安全事件"""
        events = self.security_events
        
        # 应用过滤条件
        if source_ip:
            events = [e for e in events if e.source_ip == source_ip]
        
        if threat_type:
            events = [e for e in events if e.threat_type == threat_type]
        
        if severity:
            events = [e for e in events if e.severity == severity]
        
        # 按时间倒序排列
        events = sorted(events, key=lambda x: x.timestamp, reverse=True)
        
        # 限制数量
        events = events[:limit]
        
        # 转换为字典格式
        return [
            {
                'event_id': e.event_id,
                'event_type': e.event_type,
                'threat_type': e.threat_type.value if e.threat_type else None,
                'input_data': e.input_data,
                'source_ip': e.source_ip,
                'user_agent': e.user_agent,
                'timestamp': e.timestamp.isoformat(),
                'severity': e.severity,
                'blocked': e.blocked,
                'details': e.details
            }
            for e in events
        ]
    
    def get_validation_statistics(self) -> Dict[str, Any]:
        """获取验证统计信息"""
        total_events = len(self.security_events)
        
        # 按威胁类型统计
        threat_stats = {}
        for event in self.security_events:
            if event.threat_type:
                threat_type = event.threat_type.value
                threat_stats[threat_type] = threat_stats.get(threat_type, 0) + 1
        
        # 按严重程度统计
        severity_stats = {}
        for event in self.security_events:
            severity = event.severity
            severity_stats[severity] = severity_stats.get(severity, 0) + 1
        
        # 最近24小时统计
        recent_time = datetime.now() - timedelta(hours=24)
        recent_events = [e for e in self.security_events if e.timestamp > recent_time]
        
        # 被封禁的IP统计
        blocked_events = [e for e in self.security_events if e.blocked]
        
        return {
            'total_events': total_events,
            'recent_24h_events': len(recent_events),
            'blocked_events': len(blocked_events),
            'blocked_ips': len(self.blocked_ips),
            'active_rules': len([r for r in self.validation_rules.values() if r.is_active]),
            'total_rules': len(self.validation_rules),
            'csrf_tokens': len(self.csrf_tokens),
            'rate_limit_entries': len(self.rate_limits),
            'threat_distribution': threat_stats,
            'severity_distribution': severity_stats,
            'validation_level': self.validation_level.value,
            'config': self.config
        }
    
    def export_security_report(self, start_date: Optional[datetime] = None,
                             end_date: Optional[datetime] = None) -> Dict[str, Any]:
        """导出安全报告"""
        if not start_date:
            start_date = datetime.now() - timedelta(days=7)
        if not end_date:
            end_date = datetime.now()
        
        # 过滤时间范围内的事件
        filtered_events = [
            e for e in self.security_events
            if start_date <= e.timestamp <= end_date
        ]
        
        # 统计分析
        total_events = len(filtered_events)
        blocked_events = len([e for e in filtered_events if e.blocked])
        
        # 威胁分析
        threat_analysis = {}
        for event in filtered_events:
            if event.threat_type:
                threat_type = event.threat_type.value
                if threat_type not in threat_analysis:
                    threat_analysis[threat_type] = {
                        'count': 0,
                        'blocked': 0,
                        'severity_distribution': {}
                    }
                
                threat_analysis[threat_type]['count'] += 1
                if event.blocked:
                    threat_analysis[threat_type]['blocked'] += 1
                
                severity = event.severity
                threat_analysis[threat_type]['severity_distribution'][severity] = \
                    threat_analysis[threat_type]['severity_distribution'].get(severity, 0) + 1
        
        # IP分析
        ip_analysis = {}
        for event in filtered_events:
            if event.source_ip:
                ip = event.source_ip
                if ip not in ip_analysis:
                    ip_analysis[ip] = {
                        'total_events': 0,
                        'blocked_events': 0,
                        'is_blocked': ip in self.blocked_ips,
                        'threat_types': set()
                    }
                
                ip_analysis[ip]['total_events'] += 1
                if event.blocked:
                    ip_analysis[ip]['blocked_events'] += 1
                if event.threat_type:
                    ip_analysis[ip]['threat_types'].add(event.threat_type.value)
        
        # 转换set为list以便JSON序列化
        for ip_data in ip_analysis.values():
            ip_data['threat_types'] = list(ip_data['threat_types'])
        
        return {
            'report_period': {
                'start_date': start_date.isoformat(),
                'end_date': end_date.isoformat()
            },
            'summary': {
                'total_events': total_events,
                'blocked_events': blocked_events,
                'block_rate': blocked_events / total_events if total_events > 0 else 0,
                'unique_ips': len(ip_analysis),
                'blocked_ips': len(self.blocked_ips)
            },
            'threat_analysis': threat_analysis,
            'ip_analysis': ip_analysis,
            'top_threats': sorted(
                threat_analysis.items(),
                key=lambda x: x[1]['count'],
                reverse=True
            )[:10],
            'top_attacking_ips': sorted(
                ip_analysis.items(),
                key=lambda x: x[1]['total_events'],
                reverse=True
            )[:10]
        }


# 示例使用
if __name__ == "__main__":
    # 创建输入验证服务实例
    validation_service = InputValidationService(ValidationLevel.STANDARD)
    
    print("=== 输入验证和防护服务测试 ===")
    
    # 测试SQL注入检测
    sql_injection_tests = [
        "SELECT * FROM users WHERE id = 1",
        "1' OR '1'='1",
        "'; DROP TABLE users; --",
        "UNION SELECT password FROM admin_users",
        "normal search query"
    ]
    
    print("\n1. SQL注入检测测试:")
    for test_input in sql_injection_tests:
        result = validation_service.validate_input(test_input, "sql_query", "192.168.1.100")
        print(f"输入: {test_input}")
        print(f"结果: {result.result.value}")
        print(f"威胁: {[t.value for t in result.threats_detected]}")
        print(f"清理后: {result.sanitized_data}")
        print("-" * 40)
    
    # 测试XSS检测
    xss_tests = [
        "<script>alert('XSS')</script>",
        "javascript:alert('XSS')",
        "<img src=x onerror=alert('XSS')>",
        "<div onload=alert('XSS')>content</div>",
        "normal text content"
    ]
    
    print("\n2. XSS攻击检测测试:")
    for test_input in xss_tests:
        result = validation_service.validate_input(test_input, "html_content", "192.168.1.101")
        print(f"输入: {test_input}")
        print(f"结果: {result.result.value}")
        print(f"威胁: {[t.value for t in result.threats_detected]}")
        print(f"清理后: {result.sanitized_data}")
        print("-" * 40)
    
    # 测试文件上传验证
    print("\n3. 文件上传验证测试:")
    file_tests = [
        ("document.pdf", b"PDF content here"),
        ("script.exe", b"MZ executable content"),
        ("data.csv", b"name,age\nJohn,25"),
        ("../../../etc/passwd", b"root:x:0:0:root:/root:/bin/bash"),
        ("normal_file.txt", b"This is normal text content")
    ]
    
    for filename, content in file_tests:
        result = validation_service.validate_file_upload(filename, content)
        print(f"文件: {filename}")
        print(f"有效: {result.is_valid}")
        print(f"威胁: {result.threats}")
        print(f"清理后文件名: {result.sanitized_filename}")
        print("-" * 40)
    
    # 获取统计信息
    stats = validation_service.get_validation_statistics()
    print(f"\n4. 验证统计信息:")
    print(f"总事件数: {stats['total_events']}")
    print(f"威胁分布: {stats['threat_distribution']}")
    print(f"严重程度分布: {stats['severity_distribution']}")
    print(f"活跃规则数: {stats['active_rules']}")
    
    # 生成安全报告
    report = validation_service.export_security_report()
    print(f"\n5. 安全报告摘要:")
    print(f"报告期间事件总数: {report['summary']['total_events']}")
    print(f"封禁事件数: {report['summary']['blocked_events']}")
    print(f"封禁率: {report['summary']['block_rate']:.2%}")
    print(f"涉及IP数: {report['summary']['unique_ips']}")